using System;
using UnityEngine;
using Object = UnityEngine.Object;

namespace IQIGame.Onigao.GameAOT
{
    public class HUDMesh
    {
        public Mesh m_Mesh;
        public Material m_mat;

        // public UIFont mFont;
        public BetterList<Vector3> mVerts = new BetterList<Vector3>();
        public BetterList<Vector2> mOffset = new BetterList<Vector2>();
        public BetterList<Vector2> mUvs = new BetterList<Vector2>();
        public BetterList<Color32> mCols = new BetterList<Color32>();
        public BetterList<int> mIndices = new BetterList<int>();
        public float m_Scale = 1.0f;
        //int m_nVertexExt = 0;
        int m_nOldSpriteNumb = 0;

        Texture tex;
        BetterList<HUDVertex> m_SpriteVertex = new BetterList<HUDVertex>();
        bool mDirty = false;
        bool mHaveNullVertex = false;

        // public static float s_fCameraScale = 0.8f; // [0.1, 0.8]
        public static float s_fCameraScaleX = 1.0f;
        public static float s_fCameraScaleY = 1.0f;
        public static float s_fNumberScale = 1.0f;

        public static Func<string, Shader> shaderLoad;
        
        public void SetTexture(Texture tex)
        {
            this.tex = tex;
            if (m_mat == null)
            {
                if (shaderLoad == null)
                {
                    return;
                }
                m_mat = new Material(shaderLoad.Invoke("HUD/HUDSprite"));
            }
            m_mat.SetTexture("_MainTex", tex);
            // var sprite = this.render.resLoader.LoadABAsset<Sprite>(PathConstant.GetAtlasSpritePath("HUD/Red", "Red_0"));
            // if (sprite)
            // {
            //     //为了取图集的整张texture
            //     
            //     // m_mat.SetFloat("_ReverseY", GetReserveY());
            // }
            // else
            // {
            //     Debug.LogError("Cant get sprite crit");
            // }
        }

        public Texture Texture
        {
            get { return tex; }
        }

        // public Sprite GetSpriteByAtlas(string name)
        // {
        //     if (m_atlas == null)
        //         return null;
        //     return this.render.resLoader.GetAtlasSprite(m_atlas, name);
        // }

        float GetReserveY()
        {
            if (Application.platform == RuntimePlatform.IPhonePlayer)
                return -1.0f; // IOS使用meta, 反过来
            // 主角坐下来时，也需要反过来，先不处理
            return 1.0f;
        }

        public void Release()
        {
            CleanAllVertex();
            if (m_Mesh != null)
            {
                Object.Destroy(m_Mesh);
                m_Mesh = null;
            }
            if (m_mat != null)
            {
                Object.Destroy(m_mat);
                m_mat = null;
            }
        }

        public void CleanAllVertex()
        {
            mDirty = true;
            mHaveNullVertex = false;
            m_SpriteVertex.Clear();
            tex = null;
        }

        // 功能：快速清队模型的顶点
        public void FastClearVertex()
        {
            mDirty = true;
            mHaveNullVertex = false;
            m_SpriteVertex.Clear();
        }

        public void PushHUDVertex(HUDVertex v)
        {
            mDirty = true;
            v.m_hudVertexIndex = m_SpriteVertex.size;
            m_SpriteVertex.Add(v);
        }

        public void EraseHUDVertex(HUDVertex v)
        {
            int nIndex = v.m_hudVertexIndex;
            if (nIndex >= 0 && nIndex < m_SpriteVertex.size)
            {
                if (m_SpriteVertex[nIndex] != null && v.ID == m_SpriteVertex[nIndex].ID)
                {
                    mDirty = true;
                    mHaveNullVertex = true;
                    m_SpriteVertex[nIndex] = null;
                    return;
                }
            }

            for (int i = m_SpriteVertex.size - 1; i >= 0; --i)
            {
                if (m_SpriteVertex[i] != null && m_SpriteVertex[i].ID == v.ID)
                {
                    mDirty = true;
                    mHaveNullVertex = true;
                    m_SpriteVertex[i] = null;
                    break;
                }
            }
        }

        public void VertexDirty()
        {
            mDirty = true;
        }
        public bool IsDirty()
        {
            return mDirty;
        }

        public int SpriteNumb
        {
            get { return m_SpriteVertex.size; }
        }
        public int OldSpriteNumb
        {
            get { return m_nOldSpriteNumb; }
        }

        public void UpdateLogic()
        {
            if (!mDirty)
                return;
            mDirty = false;

            if (mHaveNullVertex)
            {
                mHaveNullVertex = false;
                m_SpriteVertex.ClearNullItem();
            }
            UpdateMesh();
            m_nOldSpriteNumb = m_SpriteVertex.size;
        }

        void FillVertex()
        {
            PrepareWrite(m_SpriteVertex.size * 4);
            Vector2 vOffset = Vector2.zero;
            float fScaleX = 1.0f, fScaleY = 1.0f;
            float fCameraScaleX = s_fCameraScaleX;
            float fCameraScaleY = s_fCameraScaleY;
            //if(m_bScaleByDist)
            //{
            //    fCameraScaleX = s_fScaleXByDist;
            //    fCameraScaleY = s_fScaleYByDist;
            //}

            for (int i = 0, nSize = m_SpriteVertex.size; i < nSize; ++i)
            {
                HUDVertex v = m_SpriteVertex[i];
                v.m_hudVertexIndex = i;
                mVerts.Add(v.WorldPos);
                mVerts.Add(v.WorldPos);
                mVerts.Add(v.WorldPos);
                mVerts.Add(v.WorldPos);

                //fScaleX = fCameraScaleX * v.Scale;
                //fScaleY = fCameraScaleY * v.Scale; 
                fScaleX = fCameraScaleX * v.Scale;
                fScaleY = fCameraScaleY * v.Scale;

                vOffset = v.vecRU;
                vOffset += v.Offset;
                vOffset.x *= fScaleX;
                vOffset.y *= fScaleY;
                //vOffset += v.ScreenPos + v.Move;
                vOffset += v.Move;
                mOffset.Add(vOffset);

                vOffset = v.vecRD;
                vOffset += v.Offset;
                vOffset.x *= fScaleX;
                vOffset.y *= fScaleY;
                //vOffset += v.ScreenPos + v.Move;
                vOffset += v.Move;
                mOffset.Add(vOffset);

                vOffset = v.vecLD;
                vOffset += v.Offset;
                vOffset.x *= fScaleX;
                vOffset.y *= fScaleY;
                //vOffset += v.ScreenPos + v.Move;
                vOffset += v.Move;
                mOffset.Add(vOffset);

                vOffset = v.vecLU;
                vOffset += v.Offset;
                vOffset.x *= fScaleX;
                vOffset.y *= fScaleY;
                //vOffset += v.ScreenPos + v.Move;
                vOffset += v.Move;
                mOffset.Add(vOffset);

                mUvs.Add(v.uvRU);
                mUvs.Add(v.uvRD);
                mUvs.Add(v.uvLD);
                mUvs.Add(v.uvLU);
                mCols.Add(v.clrRD);
                mCols.Add(v.clrRU);
                mCols.Add(v.clrLU);
                mCols.Add(v.clrLD);
            }
        }

        void PrepareWrite(int nVertexNumb)
        {
            mVerts.CleanPreWrite(nVertexNumb);
            mOffset.CleanPreWrite(nVertexNumb);
            mUvs.CleanPreWrite(nVertexNumb);
            mCols.CleanPreWrite(nVertexNumb);
        }
        // 功能：填充顶点数据
        void UpdateMesh()
        {
            int nOldVertexCount = mVerts.size;
            FillVertex();

            int nLast = mVerts.size - 1;
            int nExSize = mVerts.buffer.Length;
            int nVertexCount = mVerts.size;
            if (nLast >= 0)
            {
                Vector3[] vers = mVerts.buffer;
                Vector2[] uv1s = mUvs.buffer;
                Vector2[] offs = mOffset.buffer;
                Color32[] cols = mCols.buffer;
                for (int i = mVerts.size, iMax = mVerts.buffer.Length; i < iMax; ++i)
                {
                    vers[i] = vers[nLast];
                    uv1s[i] = uv1s[nLast];
                    offs[i] = offs[nLast];
                    cols[i] = cols[nLast];
                }
            }
            mVerts.size = nExSize;
            mUvs.size = nExSize;
            mCols.size = nExSize;
            mOffset.size = nExSize;

            // 更新索引数据
            bool rebuildIndices = nOldVertexCount != nExSize;
            if (rebuildIndices)
                AdjustIndexs(nVertexCount);

            if (m_Mesh == null)
            {
                m_Mesh = new Mesh();
                m_Mesh.hideFlags = HideFlags.DontSave;
                m_Mesh.name = "hud_mesh";
                m_Mesh.MarkDynamic();
            }
            else if (rebuildIndices || m_Mesh.vertexCount != mVerts.size)
            {
                m_Mesh.Clear();
            }

            if (m_Mesh != null)
            {
                m_Mesh.vertices = mVerts.buffer;
                m_Mesh.uv = mUvs.buffer;
                m_Mesh.uv2 = mOffset.buffer;
                m_Mesh.colors32 = mCols.buffer;
                m_Mesh.triangles = mIndices.buffer;
            }
        }

        void AdjustIndexs(int nVertexCount)
        {
            int nOldSize = mIndices.size;
            int nNewSize = mVerts.size / 4 * 6;
            mIndices.CleanPreWrite(nVertexCount / 4 * 6);
            // 填充多余的
            int nMaxCount = mIndices.buffer.Length;
            int[] Indices = mIndices.buffer;

            int index = 0;
            int i = 0;
            for (; i < nVertexCount; i += 4)
            {
                Indices[index++] = i;
                Indices[index++] = i + 1;
                Indices[index++] = i + 2;

                Indices[index++] = i + 2;
                Indices[index++] = i + 3;
                Indices[index++] = i;
            }
            int nLast = nVertexCount - 1;
            for (; index < nMaxCount;)
            {
                Indices[index++] = nLast;
                Indices[index++] = nLast;
                Indices[index++] = nLast;
                Indices[index++] = nLast;
                Indices[index++] = nLast;
                Indices[index++] = nLast;
            }
            mIndices.size = index;
        }


    }
}